<template>
  <n-notification-provider>
    <n-config-provider :theme="darkTheme">
      <div class="app-container">
        <!-- 顶部区域：任务列表和日志显示 -->
        <div class="top-section">
          <div class="left-panel">
            <n-card title="任务列表" size="small">
              <!-- 新建任务按钮 -->
              <div v-if="!isProcessing" class="add-task-btn-container">
                <n-button type="primary" @click="showAddTaskForm = true">新建任务</n-button>
              </div>
              
              <!-- 任务列表 -->
              <div class="task-container">
                <n-scrollbar>
                  <div v-if="tasks.length === 0" class="empty-tasks">
                    <n-empty description="暂无任务配置" />
                  </div>
                  <div v-else class="task-list">
                    <div v-for="(task, index) in tasks" :key="task.id" class="task-item">
                      <div class="task-header">
                        <div class="task-icon">
                          <n-icon :size="20">
                            <component :is="getTaskIcon(task.type)" />
                          </n-icon>
                        </div>
                        <div class="task-info">
                          <div class="task-name">{{ getTaskTypeName(task.type) }}</div>
                          <div class="task-file-name">{{ getFileName(task.inputFile) }}</div>
                        </div>
                        <n-tag :type="getStatusType(task.status)" class="task-status">
                          {{ getStatusText(task.status) }}
                        </n-tag>
                        <div v-if="!isProcessing && task.status !== 'processing'" class="task-actions">
                          <n-button text type="error" @click="removeTask(index)">
                    <n-icon><Trash /></n-icon>
                  </n-button>
                        </div>
                      </div>
                      <div class="task-details">
                        <div class="task-detail-item">
                          <span class="task-detail-label">输出路径:</span>
                          <span class="task-detail-value">{{ task.outputDir }}</span>
                        </div>
                        <div v-if="task.interval !== undefined" class="task-detail-item">
                          <span class="task-detail-label">间隔秒数:</span>
                          <span class="task-detail-value">{{ task.interval }}s</span>
                        </div>
                      </div>
                    </div>
                  </div>
                </n-scrollbar>
              </div>
            </n-card>
          </div>
          <div class="right-panel">
            <n-card title="处理日志" size="small">
              <div class="log-container">
                <n-scrollbar>
                  <div v-for="(log, index) in logs" :key="index" class="log-item">
                    <n-tag :type="getLogType(log.type)" size="small">
                      {{ log.type }}
                    </n-tag>
                    <span class="log-time">{{ log.time }}</span>
                    <span class="log-message">{{ log.message }}</span>
                  </div>
                </n-scrollbar>
              </div>
            </n-card>
          </div>
        </div>

        <!-- 中部区域：处理按钮 -->
        <div class="middle-section">
          <div style="display: flex; gap: 10px; width: 95%;">
            <n-button 
              type="primary" 
              size="large" 
              :loading="isProcessing"
              @click="handleProcessing"
              style="flex: 1; height: 70px; font-size: 24px;"
              :disabled="tasks.length === 0"
            >
              <template #icon>
                  <n-icon>
                    <PlayCircle v-if="!isProcessing" />
                    <PauseCircle v-else />
                  </n-icon>
                </template>
              {{ isProcessing ? '暂停处理' : '开始处理' }}
            </n-button>
          </div>
        </div>

        <!-- 底部区域：状态栏 -->
        <div class="bottom-section">
          <n-layout-footer bordered>
            <div class="status-bar">
              <n-button text type="primary" @click="showHelp">帮助文档</n-button>
              <n-button text type="primary" @click="showAbout">关于</n-button>
              <span>版本: {{ version }}</span>
            </div>
          </n-layout-footer>
        </div>

        <!-- 新建任务弹窗 -->
        <n-modal v-model:show="showAddTaskForm" title="新建任务" :destroy-on-close="true" :mask-opacity="0.2">
          <div class="add-task-form">
            <n-form ref="taskFormRef" :model="newTask" layout="vertical">
              <n-form-item label="任务类型" path="type">
                <n-select v-model:value="newTask.type" placeholder="选择任务类型" :options="taskTypeOptions" />
              </n-form-item>
              <n-form-item label="输入文件" v-if="newTask.type === 'mp4-to-m3u8' || newTask.type === 'panorama-frames' || newTask.type === 'panorama-projections'" path="inputFile">
            <div class="file-selector">
              <n-input v-model:value="newTask.inputFile" placeholder="请选择输入文件" readonly />
              <n-button @click="selectInputFile">浏览</n-button>
            </div>
          </n-form-item>
          
          <n-form-item label="全景照片文件夹" v-if="newTask.type === 'panorama-photo-projections'" path="inputFile">
            <div class="file-selector">
              <n-input v-model:value="newTask.inputFile" placeholder="请选择全景照片文件夹" readonly />
              <n-button @click="selectInputDirectory">浏览</n-button>
            </div>
          </n-form-item>
              <n-form-item label="输出目录" path="outputDir">
                <div class="file-selector">
                  <n-input v-model:value="newTask.outputDir" placeholder="请选择存储路径" readonly />
                  <n-button @click="selectOutputDir">浏览</n-button>
                </div>
              </n-form-item>
              <n-form-item v-if="newTask.type === 'panorama-frames' || newTask.type === 'panorama-projections'" label="间隔秒数" path="interval">
            <n-input-number 
              v-model:value="newTask.interval" 
              placeholder="请输入间隔秒数" 
              :min="0.1" 
              :max="100" 
              :step="0.1"
            />
          </n-form-item>
          
          <n-form-item v-if="newTask.type === 'panorama-photo-projections' || newTask.type === 'panorama-projections'" label="投影类型" path="projectionType">
            <n-select 
              v-model:value="newTask.projectionType" 
              placeholder="请选择投影类型" 
              :options="[
                { label: '5视图 (前、后、左、右、上)', value: '5views' },
                { label: '8视图 (前/后/左/右 俯视/仰视)', value: '8views' }
              ]"
            />
          </n-form-item>
          
          <n-form-item v-if="newTask.type === 'panorama-frames' || newTask.type === 'panorama-projections' || newTask.type === 'panorama-photo-projections'" label="输出分辨率" path="resolution">
            <n-select 
              v-model:value="newTask.resolution" 
              placeholder="请选择输出分辨率" 
              :options="[
                { label: '7680x4320 (8K)', value: '7680x4320' },
                { label: '3840x2160 (4K)', value: '3840x2160' },
                { label: '1920x1080 (1080P)', value: '1920x1080' },
                { label: '1280x720 (720P)', value: '1280x720' }
              ]"
            />
          </n-form-item>
            </n-form>
            <div class="form-actions">
              <n-button @click="showAddTaskForm = false">取消</n-button>
              <n-button type="primary" @click="addTask">确定</n-button>
            </div>
          </div>
        </n-modal>
      </div>
    </n-config-provider>
  </n-notification-provider>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
import { darkTheme, NConfigProvider, NNotificationProvider, NButton, NCard, NEmpty, NScrollbar, NTag, NLayoutFooter, NIcon, NSelect, NInput, NInputNumber, NForm, NFormItem, NModal } from 'naive-ui'
import { PlayCircle, PauseCircle, Film, Image, Crop, Trash, Grid } from '@vicons/ionicons5'

// 任务类型定义
type TaskType = 'mp4-to-m3u8' | 'panorama-frames' | 'panorama-projections' | 'panorama-photo-projections'
type TaskStatus = 'pending' | 'processing' | 'success' | 'failed'

type Resolution = '7680x4320' | '3840x2160' | '1920x1080' | '1280x720'

// 任务接口
interface Task {
  id: string
  type: TaskType
  inputFile: string
  outputDir: string
  interval?: number
  projectionType?: '5views' | '8views'
  resolution?: Resolution
  status: TaskStatus
}

// 任务类型选项
const taskTypeOptions = [
  { label: 'MP4转M3U8', value: 'mp4-to-m3u8' },
  { label: '全景视频抽帧', value: 'panorama-frames' },
  { label: '全景视频透视图提取', value: 'panorama-projections' },
  { label: '全景照片透视图提取', value: 'panorama-photo-projections' }
]

// 任务列表和状态
const tasks = ref<Task[]>([])
const isProcessing = ref(false)
const processingTaskIndex = ref(-1)
const showAddTaskForm = ref(false)
const logs = ref<Array<{type: string, time: string, message: string}>>([])
const version = ref('1.0.0')

// 新建任务表单数据
const newTask = ref<Task>({
  id: '',
  type: 'panorama-projections',
  inputFile: '',
  outputDir: '',
  interval: 0.5,
  projectionType: '8views',
  resolution: '1920x1080',
  status: 'pending'
})

const taskFormRef = ref()

// 添加日志
const addLog = (type: string, message: string) => {
  const time = new Date().toLocaleTimeString()
  logs.value.push({ type, time, message })
}

// 获取日志类型对应的颜色
const getLogType = (type: string) => {
  const typeMap: Record<string, any> = {
    'INFO': 'info',
    'WARN': 'warning',
    'ERROR': 'error',
    'SUCCESS': 'success'
  }
  return typeMap[type] || 'default'
}

// 获取任务类型图标
const getTaskIcon = (type: TaskType) => {
  const iconMap: Record<TaskType, any> = {
    'mp4-to-m3u8': Film,
    'panorama-frames': Image,
    'panorama-projections': Crop,
    'panorama-photo-projections': Grid
  }
  return iconMap[type]
}

// 获取任务类型名称
const getTaskTypeName = (type: TaskType) => {
  const nameMap: Record<TaskType, string> = {
    'mp4-to-m3u8': 'MP4转M3U8',
    'panorama-frames': '全景视频抽帧',
    'panorama-projections': '全景视频5视图提取',
    'panorama-photo-projections': '全景照片透视图提取'
  }
  return nameMap[type]
}

// 获取任务状态文本
const getStatusText = (status: TaskStatus) => {
  const statusMap: Record<TaskStatus, string> = {
    'pending': '待处理',
    'processing': '处理中',
    'success': '处理完成',
    'failed': '处理失败'
  }
  return statusMap[status]
}

// 获取任务状态类型（颜色）
const getStatusType = (status: TaskStatus) => {
  const statusMap: Record<TaskStatus, any> = {
    'pending': 'default',
    'processing': 'info',
    'success': 'success',
    'failed': 'error'
  }
  return statusMap[status]
}

// 获取文件名（不含路径）
const getFileName = (filePath: string) => {
  const parts = filePath.split('\\')
  return parts[parts.length - 1]
}

// 选择输入文件
const selectInputFile = async () => {
  try {
    const filePath = await window.electronAPI.dialog.openFile({
      title: '选择输入文件',
      filters: [
        { name: '视频文件', extensions: ['mp4', 'mov', 'avi', 'mkv'] }
      ]
    })
    if (filePath) {
      newTask.value.inputFile = filePath
    }
  } catch (error) {
    addLog('ERROR', `选择文件失败: ${error instanceof Error ? error.message : String(error)}`)
  }
}

// 选择输入目录
const selectInputDirectory = async () => {
  try {
    const directory = await window.electronAPI.dialog.openDirectory()
    if (directory) {
      newTask.value.inputFile = directory
    }
  } catch (error) {
    addLog('ERROR', `选择目录失败: ${error instanceof Error ? error.message : String(error)}`)
  }
}

// 选择输出目录
const selectOutputDir = async () => {
  try {
    const dirPath = await window.electronAPI.dialog.openDirectory()
    if (dirPath) {
      newTask.value.outputDir = dirPath
    }
  } catch (error) {
    addLog('ERROR', `选择目录失败: ${error}`)
  }
}

// 添加任务
const addTask = () => {
  if (!newTask.value.inputFile || !newTask.value.outputDir) {
    addLog('WARN', '请填写完整的任务信息')
    return
  }

  const task: Task = {
    id: Date.now().toString(),
    type: newTask.value.type,
    inputFile: newTask.value.inputFile,
    outputDir: newTask.value.outputDir,
    status: 'pending'
  }

  // 对于需要间隔的任务，添加间隔参数
  if (task.type === 'panorama-frames' || task.type === 'panorama-projections') {
    task.interval = newTask.value.interval || 0.5
  }
  
  // 对于全景照片和视频透视图提取任务，添加投影类型参数
  if (task.type === 'panorama-photo-projections' || task.type === 'panorama-projections') {
    task.projectionType = newTask.value.projectionType || '5views'
  }
  
  // 对于需要分辨率的任务，添加分辨率参数
  if (task.type === 'panorama-frames' || task.type === 'panorama-projections' || task.type === 'panorama-photo-projections') {
    task.resolution = newTask.value.resolution || '1920x1080'
  }

  tasks.value.push(task)
  showAddTaskForm.value = false
  
  // 重置表单
  newTask.value = {
    id: '',
    type: 'mp4-to-m3u8',
    inputFile: '',
    outputDir: '',
    interval: 0.5,
    status: 'pending'
  }
  
  addLog('INFO', `已添加任务: ${getTaskTypeName(task.type)} - ${getFileName(task.inputFile)}`)
}

// 移除任务
const removeTask = (index: number) => {
  const task = tasks.value[index]
  tasks.value.splice(index, 1)
  addLog('INFO', `已移除任务: ${getTaskTypeName(task.type)} - ${getFileName(task.inputFile)}`)
}

// 处理任务
const processTask = async (task: Task) => {
  try {
    addLog('INFO', `开始处理任务: ${getTaskTypeName(task.type)} - ${getFileName(task.inputFile)}`)
    
    // 根据任务类型调用不同的处理函数
    switch (task.type) {
      case 'mp4-to-m3u8':
        await convertVideoToM3U8(task.inputFile, task.outputDir)
        break
      case 'panorama-frames':
        await extractPanoramaFrames(task.inputFile, task.outputDir, task.interval, task.resolution)
        break
      case 'panorama-projections':
        await extractPanoramaProjections(task.inputFile, task.outputDir, task.interval, task.projectionType || '5views', task.resolution)
        break
      case 'panorama-photo-projections':
        await extractPanoramaPhotoProjections(task.inputFile, task.outputDir, task.projectionType || '5views', task.resolution)
        break
    }
    
    // 更新任务状态为成功
    task.status = 'success'
    addLog('SUCCESS', `任务处理完成: ${getTaskTypeName(task.type)} - ${getFileName(task.inputFile)}`)
  } catch (error) {
    // 更新任务状态为失败
    task.status = 'failed'
    addLog('ERROR', `任务处理失败: ${error}`)
  }
}

// 开始/暂停处理
const handleProcessing = async () => {
  if (isProcessing.value) {
    // 暂停处理
    isProcessing.value = false
    addLog('INFO', '已暂停处理任务')
  } else {
    // 开始处理
    isProcessing.value = true
    addLog('INFO', '开始批量处理任务')
    
    try {
      // 处理所有待处理的任务
      for (let i = 0; i < tasks.value.length; i++) {
        const task = tasks.value[i]
        if (task.status === 'pending' && isProcessing.value) {
          processingTaskIndex.value = i
          task.status = 'processing'
          await processTask(task)
          processingTaskIndex.value = -1
        }
        
        // 如果处理被暂停，跳出循环
        if (!isProcessing.value) {
          break
        }
      }
    } finally {
      if (isProcessing.value) {
        isProcessing.value = false
        addLog('INFO', '所有任务处理完成')
      }
    }
  }
}

// FFMpeg视频转换函数
const convertVideoToM3U8 = async (inputFile: string, outputDir: string) => {
  return new Promise<void>(async (resolve, reject) => {
    try {
      // 监听FFMpeg日志
      window.electronAPI.ffmpeg.onLog((log: string) => {
        addLog('INFO', log)
      })

      // 调用FFMpeg转换
      const result = await window.electronAPI.ffmpeg.convertToM3U8(inputFile, outputDir)
      
      if (result.success) {
        resolve()
      } else {
        reject(new Error(result.error || '转换失败'))
      }
    } catch (error) {
      reject(error)
    }
  })
}

// FFMpeg全景视频抽帧函数
const extractPanoramaFrames = async (inputFile: string, outputDir: string, interval?: number, resolution?: Resolution) => {
  return new Promise<void>(async (resolve, reject) => {
    try {
      // 监听FFMpeg日志
      window.electronAPI.ffmpeg.onLog((log: string) => {
        addLog('INFO', log)
      })

      // 调用FFMpeg抽帧
      const result = await window.electronAPI.ffmpeg.extractPanoramaFrames(inputFile, outputDir, interval, resolution)
      
      if (result.success) {
        resolve()
      } else {
        reject(new Error(result.error || '抽帧失败'))
      }
    } catch (error) {
      reject(error)
    }
  })
}

// FFMpeg全景视频提取透视图函数
const extractPanoramaProjections = async (inputFile: string, outputDir: string, interval?: number, projectionType?: '5views' | '8views', resolution?: Resolution) => {
  return new Promise<void>(async (resolve, reject) => {
    try {
      // 监听FFMpeg日志
      window.electronAPI.ffmpeg.onLog((log: string) => {
        addLog('INFO', log)
      })

      // 调用FFMpeg提取透视图
      const result = await window.electronAPI.ffmpeg.extractPanoramaProjections(inputFile, outputDir, interval, projectionType, resolution)
      
      if (result.success) {
        resolve()
      } else {
        reject(new Error(result.error || '透视图提取失败'))
      }
    } catch (error) {
      reject(error)
    }
  })
}

// FFMpeg全景照片提取透视图函数
const extractPanoramaPhotoProjections = async (inputDir: string, outputDir: string, projectionType: '5views' | '8views', resolution?: Resolution) => {
  return new Promise<void>(async (resolve, reject) => {
    try {
      // 监听FFMpeg日志
      window.electronAPI.ffmpeg.onLog((log: string) => {
        addLog('INFO', log)
      })

      // 调用FFMpeg提取全景照片透视图
      const result = await window.electronAPI.ffmpeg.extractPanoramaPhotoProjections(inputDir, outputDir, projectionType, resolution)
      
      if (result.success) {
        resolve()
      } else {
        reject(new Error(result.error || '全景照片透视图提取失败'))
      }
    } catch (error) {
      reject(error)
    }
  })
}

// 显示帮助文档
const showHelp = () => {
  addLog('INFO', '显示帮助文档')
  // 打开浏览器并跳转到指定的CSDN博客地址
  window.open('https://blog.csdn.net/xiaopeixiaojun?spm=1011.2415.3001.10640', '_blank')
}

// 显示关于信息
const showAbout = () => {
  addLog('INFO', '显示关于信息')
  window.electronAPI.window.openAbout()
}

// 组件生命周期
onMounted(async() => {
  addLog('INFO', '应用启动')
})

onUnmounted(() => {
  // 组件卸载时的清理工作
})
</script>

<style scoped>
.app-container {
  width: 1024px;
  height: 768px;
  display: flex;
  flex-direction: column;
}

.top-section {
  flex: 1;
  display: flex;
  height: calc(100% - 160px); /* 总高度减去中部和底部区域 */
}

.left-panel {
  flex: 4; /* 左侧占40% */
  padding: 10px;
}

.right-panel {
  flex: 6; /* 右侧占60% */
  padding: 10px;
}

.middle-section {
  height: 100px;
  display: flex;
  justify-content: center;
  align-items: center;
  background: var(--n-color-embedded);
}

.process-button {
  width: 95%;
  height: 70px;
  font-size: 24px;
}

.bottom-section {
  height: 70px;
}

.status-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 20px;
  height: 100%;
}

/* 新增：任务列表样式 */
.add-task-btn-container {
  margin-bottom: 10px;
  padding: 0 10px;
}

.task-container {
  height: 450px;
}

.task-list {
  padding: 0 10px;
}

.empty-tasks {
  padding: 20px 0;
}

.task-item {
  margin-bottom: 10px;
  padding: 10px;
  border: 1px solid var(--n-border-color);
  border-radius: 6px;
  background-color: var(--color-background-soft);
  transition: all 0.3s ease;
}

.task-item:hover {
  border-color: var(--n-primary-color);
}

.task-header {
  display: flex;
  align-items: center;
  margin-bottom: 8px;
}

.task-icon {
  margin-right: 10px;
  color: var(--n-primary-color);
}

.task-info {
  flex: 1;
  min-width: 0;
}

.task-name {
  font-weight: 500;
  margin-bottom: 2px;
}

.task-file-name {
  font-size: 12px;
  color: var(--n-text-color-disabled);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.task-status {
  margin-right: 10px;
  flex-shrink: 0;
}

.task-actions {
  flex-shrink: 0;
}

.task-details {
  padding-top: 8px;
  border-top: 1px solid var(--n-border-color);
  font-size: 12px;
}

.task-detail-item {
  margin-bottom: 4px;
}

.task-detail-label {
  color: var(--n-text-color-disabled);
  margin-right: 8px;
}

.task-detail-value {
  color: var(--n-text-color);
  word-break: break-all;
}

/* 新增：新建任务表单样式 */
.add-task-form {
  max-width: 500px;
  margin: 0 auto;
  padding: 20px;
  background-color: var(--color-background-soft);
  border-radius: 8px;
}

.file-selector {
  display: flex;
  gap: 8px;
  align-items: center;
}

.file-selector .n-input {
  flex: 1;
}

.form-actions {
  margin-top: 20px;
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}

/* 日志容器样式 */
.log-container {
  height: 520px;
}

.log-item {
  display: flex;
  align-items: center;
  margin-bottom: 8px;
  padding: 4px;
  border-bottom: 1px solid var(--n-border-color);
}

.log-time {
  margin: 0 8px;
  color: var(--n-text-color-disabled);
  font-size: 12px;
}

.log-message {
  flex: 1;
  font-family: monospace;
  font-size: 12px;
}
</style>